using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Collections;
using System.Windows.Forms;
using System.Threading;
using RSSRadio.Model;

namespace RSSRadio.Model
{
	///<summary>
	///   - class object which holds an ArrayList of PodcastInfo objects   
	///</summary>
	[XmlRoot("PodcastList")]
	public class PodcastList: PodcastUpdateListenerReplicator
	{
		private ArrayList ListPodcast;
		///<summary>
		///   - constructor<br/>
		///   - initialize the ArrayList ListPodcast<br/>
		///</summary>
		public PodcastList()
		{
			ListPodcast = new ArrayList();
		}

		[XmlElement("PodcastInfo")]
		public PodcastInfo[] PodcastInfo
		{
			get
			{
				PodcastInfo[] items = new PodcastInfo[ListPodcast.Count];
				ListPodcast.CopyTo(items);
				return items;
			}
			set
			{
				if (value == null) return;
				PodcastInfo[] items = (PodcastInfo[])value;
				ListPodcast.Clear();
				foreach (PodcastInfo item in items)
					ListPodcast.Add(item);
			}
		}

		public PodcastInfo this[int index]
		{
			get
			{
				return (PodcastInfo)ListPodcast[index];
			}
			set
			{
				ListPodcast[index] = (PodcastInfo)value;
			}
		}

		public int Count
		{
			get
			{
				return ListPodcast.Count;
			}
		}

		///<summary>
		///   - parameters : item - a PodcastInfo object<br/>
		///   - adds PodcastInfo object to ArrayList    <br/>
		///</summary>
		public int AddItem(PodcastInfo item)
		{
			try
			{
				ListPodcast.Add(item);
                this.ListPodcast.Sort();
                PodcastAdded(item);
			}
			catch
			{
				return 0;
			}
			return 1;
		}

		///<summary>
		///   - parameters : item - a PodcastInfo object<br/>
		///   - removes an object from arraylist and delete the coresponding file  <br/>
		///</summary>
		public void RemoveItem(PodcastInfo item)
		{
            RemoveItemPrivate(item);
            SaveToXml();
        }

        private void RemoveItemPrivate(PodcastInfo item)
        {
            // delete the media file
            try
            {
                if (File.Exists(item.FilePath))
                    File.Delete(item.FilePath);
            }
            catch
            {
                try
                {
                    WinApi.CloseMediaPlayer();
                    Thread.Sleep(1000);

                    if (File.Exists(item.FilePath))
                        File.Delete(item.FilePath);
                }
                catch
                {
                    MessageBox.Show("Cannot delete file.");
                    //return;
                }
            }

            // remove from xml and save it
            ListPodcast.Remove(item);

            // Notify others
            PodcastRemoved(item);
        }

        public bool Contains(EpisodeDetails episode)
		{
			foreach (PodcastInfo info in this.ListPodcast)
			{
                if (info.Details.Url.ToString() == episode.Url.ToString() & info.Details.Date == episode.Date)
					return true;
			}

			return false;
		}

		public bool Contains(string fileName)
		{
			foreach (PodcastInfo info in this.ListPodcast)
			{
				if (info.FilePath == fileName)
					return true;
			}

			return false;
		}

		public PodcastInfo GetInfo(string fileName)
		{
			foreach (PodcastInfo info in this.ListPodcast)
			{
				if (info.FilePath == fileName)
					return info;
			}

			return null;
		}

		public static PodcastList LoadFromXml(string xmlPath)
		{
			return Load(xmlPath);
		}

		public static PodcastList LoadFromXml()
		{
#if MOBILE
			string xmlPath = Globals.AppSettings.DownloadedPodcastListXmlLoc;
#endif
#if DESKTOP
			string xmlPath = Globals.DownloadedPodcastListFileLoc;
#endif

			return Load(xmlPath);
		}

		private static PodcastList Load(string xmlPath)
		{
			if (File.Exists(xmlPath))
			{
				PodcastList podcasts;
				XmlSerializer serializer = new XmlSerializer(typeof(PodcastList));

				try
				{
                    TextReader tr = new StreamReader(xmlPath);
                    try
                    {
                        podcasts = (PodcastList)serializer.Deserialize(tr);
                    }
                    finally
                    {
                        tr.Close();
                    }
				}
				catch (Exception ex)
				{
					if (ex.Message.StartsWith("There is an error in XML document")) // corrupted file
					{
                        File.Delete(xmlPath);
						return Load(xmlPath);
					}
					else
						return null;
				}

				return podcasts;
			}
			else
			{
				// create an empty Podcast list and save it to disk
				PodcastList tmp = new PodcastList();
				tmp.SaveToXml(xmlPath);
				return tmp;
			}
		}

		///<summary>
		///   - Writes this object to aa XML file <br/>
		///</summary>
		public void SaveToXml(string xmlPath)
		{
			this.Save(xmlPath);
		}

		///<summary>
		///   - Writes this object to aa XML file <br/>
		///</summary>
		public void SaveToXml()
		{
#if MOBILE
			string xmlPath = Globals.AppSettings.DownloadedPodcastListXmlLoc;
#endif
#if DESKTOP
			string xmlPath = Globals.DownloadedPodcastListFileLoc;
#endif

			this.Save(xmlPath);
		}

		private void Save(string xmlPath)
		{
            lock (this)
            {
                TextWriter tw = null;

                try
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(PodcastList));

                    if (File.Exists(xmlPath))
                        File.Delete(xmlPath);

                    tw = new StreamWriter(xmlPath);
                    this.ListPodcast.Sort();
                    serializer.Serialize(tw, this);
                    tw.Close();
                }
                catch (Exception ex)
                {
                    if (tw != null)
                        tw.Close();

                    MessageBox.Show("Unable to save configuration file: " + ex.Message, "Warning");
                }
            }
		}

        public void Purge(object o)
        {
            SubscriptionManager sm = Globals.getSubscriptionManager();
            DateTime now = DateTime.Now;
            List<PodcastInfo> toRemove = new List<PodcastInfo>();
            foreach (PodcastInfo info in this.ListPodcast)
            {
                Subscription feed =  sm.getSubscriptionByURL(info.FeedUrl);
                TimeSpan ts = now.Subtract(info.PubDateToDateTime());
                int retnetion = (feed != null)?feed.RetnetionDays:Globals.AppSettings.podcastExpirationDays;
                if (ts.Days > retnetion)
                {
                    toRemove.Add(info);
                }
            }
            foreach(PodcastInfo obsoletePodcast in toRemove)
            {
                RemoveItemPrivate(obsoletePodcast);
            }
            SaveToXml();

        }
		/// <summary>
		/// Converts the object to HTML for displaying
		/// </summary>
		public string ToMobileHTML()
		{
			StringBuilder sb = new StringBuilder("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head><title>Downloaded Episodes</title></head><body><table summary=\"Downloaded Episodes\" cellspacing=5>");

			foreach (PodcastInfo podInfo in this.ListPodcast)
			{
				sb.Append("<tr valign=\"top\"><td width=30%>");
				sb.Append(podInfo.FeedName);
				sb.Append("</a></td><td>");
				sb.Append("<a href=\"file://");
				sb.Append(podInfo.FilePath);
				sb.Append("\">");
				sb.Append(podInfo.Details.Title);
				sb.Append("<img src=\"file://\\storage card\\pp\\images\\speaker.png\"></td></tr>");
			}
			sb.Append("</table></body></html>");
			string pageHTML = sb.ToString();
			return pageHTML;
		}

#if DESKTOP
		/// <summary>
		/// Converts the object to HTML for the desktop
		/// </summary>
		/// <returns></returns>
		public string ToDesktopHTML()
		{
			StringBuilder sb = new StringBuilder("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head><title>Downloaded Episodes</title></head><body><table summary=\"Downloaded Episodes\" cellspacing=5>");

			foreach (PodcastInfo podInfo in this.ListPodcast)
			{
				sb.Append("<tr valign=\"top\"><td width=30%><strong>");
				sb.Append(podInfo.Name);
				sb.Append("</strong></td><td><strong>");
				sb.Append(podInfo.EpisodeTitle);
				sb.Append("</strong></td></tr>");
				sb.Append("<tr valign=\"top\"><td>");
				sb.Append(podInfo.PubDate);
				sb.Append("<br>");
				sb.Append("<a href=\"pocketpod://play/?");
				sb.Append(podInfo.FilePath);
				sb.Append("\"><img src=\"file:///" + Globals.PlayIconFileName + "\" border=\"0\">Play</a> &nbsp;&nbsp;<a href=\"pocketpod://dele/?");
				sb.Append(podInfo.FilePath);
				sb.Append("\">Delete</a></td><td>");
				sb.Append(podInfo.Description);
				sb.Append("</td></tr><tr height=15></tr>");
			}
			sb.Append("</table></body></html>");
			string pageHTML = sb.ToString();
			return pageHTML;
		}
#endif

#if DESKTOP
		/// <summary>
		/// Removes a podcast from the list of downloaded podcasts and deletes its media file
		/// </summary>
		/// <param name="podcast"></param>
		public void DeletePodcast(PodcastInfo podcast)
		{
			// delete the media file
			try
			{
				if (File.Exists(podcast.FilePath))
					File.Delete(podcast.FilePath);
			}
			catch (Exception ex)
			{
				try
				{
					if (File.Exists(podcast.FilePath))
						File.Delete(podcast.FilePath);
				}
				catch (Exception ex2)
				{
					MessageBox.Show("Error deleting file.");
					return;
				}
			}

			this.RemoveItem(podcast);
		}
#endif
	}
}
